<#
.SYNOPSIS
    Silly Tavern 一键部署脚本 - 视觉增强版
.DESCRIPTION
    全自动安装 Silly Tavern 及其依赖项（Git、Node.js）
    使用国内镜像源，优化下载速度
    提供精美的视觉界面和进度反馈
.AUTHOR
    Claude Code - Anthropic
.VERSION
    2.0
#>

# 设置控制台编码为UTF-8，确保中文正常显示
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8

# 设置错误处理
$ErrorActionPreference = "Stop"

#region 辅助函数定义

# 显示欢迎横幅
function Show-WelcomeBanner {
    Clear-Host
    Write-Host ""
    Write-Host "  ███████╗██╗██╗     ██╗  ██╗   ██╗    ████████╗ █████╗ ██╗   ██╗███████╗██████╗ ███╗   ██╗" -ForegroundColor Cyan
    Write-Host "  ██╔════╝██║██║     ██║  ╚██╗ ██╔╝    ╚══██╔══╝██╔══██╗██║   ██║██╔════╝██╔══██╗████╗  ██║" -ForegroundColor Cyan
    Write-Host "  ███████╗██║██║     ██║   ╚████╔╝        ██║   ███████║██║   ██║█████╗  ██████╔╝██╔██╗ ██║" -ForegroundColor Blue
    Write-Host "  ╚════██║██║██║     ██║    ╚██╔╝         ██║   ██╔══██║╚██╗ ██╔╝██╔══╝  ██╔══██╗██║╚██╗██║" -ForegroundColor Blue
    Write-Host "  ███████║██║███████╗███████╗██║          ██║   ██║  ██║ ╚████╔╝ ███████╗██║  ██║██║ ╚████║" -ForegroundColor DarkCyan
    Write-Host "  ╚══════╝╚═╝╚══════╝╚══════╝╚═╝          ╚═╝   ╚═╝  ╚═╝  ╚═══╝  ╚══════╝╚═╝  ╚═╝╚═╝  ╚═══╝" -ForegroundColor DarkCyan
    Write-Host ""
    Write-Host "  ╔════════════════════════════════════════════════════════════════════════════════════════╗" -ForegroundColor Magenta
    Write-Host "  ║                    🎭 Silly Tavern 全自动一键部署脚本 🎭                              ║" -ForegroundColor Magenta
    Write-Host "  ║                         让AI角色扮演触手可及！                                        ║" -ForegroundColor Magenta
    Write-Host "  ╚════════════════════════════════════════════════════════════════════════════════════════╝" -ForegroundColor Magenta
    Write-Host ""
    Write-Host "  💡 提示: 本脚本将自动完成所有安装步骤，请保持网络畅通" -ForegroundColor Yellow
    Write-Host "  🚀 使用国内镜像源，下载速度更快！" -ForegroundColor Yellow
    Write-Host ""
    Start-Sleep -Seconds 2
}

# 显示章节标题
function Show-Section {
    param(
        [string]$Title,
        [string]$Color = "Green"
    )
    Write-Host ""
    Write-Host "╔═══════════════════════════════════════════════════════════════════╗" -ForegroundColor $Color
    Write-Host "║  $Title" -ForegroundColor $Color
    Write-Host "╚═══════════════════════════════════════════════════════════════════╝" -ForegroundColor $Color
    Write-Host ""
}

# 美化的进度条下载函数
function Download-FileWithProgress {
    param(
        [string]$Url,
        [string]$OutputPath,
        [string]$Description = "下载中"
    )
    
    try {
        $webClient = New-Object System.Net.WebClient
        $webClient.Headers.Add("User-Agent", "Mozilla/5.0")
        
        # 注册进度事件
        $progressEventHandler = {
            param($sender, $e)
            if ($e.TotalBytesToReceive -gt 0) {
                $percentComplete = [math]::Round(($e.BytesReceived / $e.TotalBytesToReceive) * 100)
                $receivedMB = [math]::Round($e.BytesReceived / 1MB, 2)
                $totalMB = [math]::Round($e.TotalBytesToReceive / 1MB, 2)
                
                # 构建进度条
                $barLength = 40
                $filledLength = [math]::Floor($barLength * $percentComplete / 100)
                $bar = ("█" * $filledLength) + ("░" * ($barLength - $filledLength))
                
                $statusMessage = "[$bar] $percentComplete% - $receivedMB MB / $totalMB MB"
                
                Write-Progress -Activity $Description `
                    -Status $statusMessage `
                    -PercentComplete $percentComplete
            }
        }
        
        Register-ObjectEvent -InputObject $webClient -EventName DownloadProgressChanged `
            -SourceIdentifier WebClient.DownloadProgressChanged `
            -Action $progressEventHandler | Out-Null
        
        # 开始下载
        $webClient.DownloadFileAsync($Url, $OutputPath)
        
        # 等待下载完成
        while ($webClient.IsBusy) {
            Start-Sleep -Milliseconds 100
        }
        
        # 清理事件
        Unregister-Event -SourceIdentifier WebClient.DownloadProgressChanged -ErrorAction SilentlyContinue
        Write-Progress -Activity $Description -Completed
        
        $webClient.Dispose()
        
        Write-Host "✅ 下载完成: $OutputPath" -ForegroundColor Green
        return $true
    }
    catch {
        Write-Host "❌ 下载失败: $_" -ForegroundColor Red
        return $false
    }
}

# 检查命令是否存在
function Test-CommandExists {
    param([string]$Command)
    $null -ne (Get-Command $Command -ErrorAction SilentlyContinue)
}

# 安装Git
function Install-Git {
    Show-Section "📦 步骤 2: 安装 Git 版本控制系统" "Cyan"
    
    Write-Host "🔍 正在检测 Git 安装状态..." -ForegroundColor Yellow
    
    if (Test-CommandExists "git") {
        Write-Host "✅ Git 已安装，跳过此步骤" -ForegroundColor Green
        git --version
        return
    }
    
    Write-Host "⚠️  未检测到 Git，开始自动安装..." -ForegroundColor Yellow
    
    # 从淘宝镜像获取最新版本（这里使用固定的稳定版本）
    $gitVersion = "2.43.0"
    $gitUrl = "https://registry.npmmirror.com/-/binary/git-for-windows/v$gitVersion.windows.1/Git-$gitVersion-64-bit.exe"
    $gitInstaller = "$env:TEMP\GitInstaller.exe"
    
    Write-Host "📥 正在从淘宝镜像下载 Git $gitVersion ..." -ForegroundColor Cyan
    
    if (Download-FileWithProgress -Url $gitUrl -OutputPath $gitInstaller -Description "🚀 正在从国内镜像快马加鞭下载 Git...") {
        Write-Host "🔧 正在静默安装 Git，请稍候..." -ForegroundColor Cyan
        
        # 静默安装参数
        $installArgs = "/VERYSILENT /NORESTART /NOCANCEL /SP- /CLOSEAPPLICATIONS /RESTARTAPPLICATIONS /COMPONENTS=`"icons,ext\reg\shellhere,assoc,assoc_sh`""
        Start-Process -FilePath $gitInstaller -ArgumentList $installArgs -Wait -NoNewWindow
        
        # 刷新环境变量
        $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
        
        # 清理安装文件
        Remove-Item $gitInstaller -Force -ErrorAction SilentlyContinue
        
        Write-Host "✅ Git 安装完成！" -ForegroundColor Green
    }
    else {
        throw "Git 下载失败，请检查网络连接"
    }
}

# 安装Node.js
function Install-NodeJS {
    Show-Section "📦 步骤 3: 安装 Node.js 运行环境" "Cyan"
    
    Write-Host "🔍 正在检测 Node.js 安装状态..." -ForegroundColor Yellow
    
    if (Test-CommandExists "node") {
        Write-Host "✅ Node.js 已安装，跳过此步骤" -ForegroundColor Green
        node --version
        npm --version
        return
    }
    
    Write-Host "⚠️  未检测到 Node.js，开始自动安装..." -ForegroundColor Yellow
    
    # 使用最新LTS版本
    $nodeVersion = "20.11.0"
    $nodeUrl = "https://registry.npmmirror.com/-/binary/node/v$nodeVersion/node-v$nodeVersion-x64.msi"
    $nodeInstaller = "$env:TEMP\NodeInstaller.msi"
    
    Write-Host "📥 正在从淘宝镜像下载 Node.js $nodeVersion LTS..." -ForegroundColor Cyan
    
    if (Download-FileWithProgress -Url $nodeUrl -OutputPath $nodeInstaller -Description "🚀 正在从国内镜像快马加鞭下载 Node.js...") {
        Write-Host "🔧 正在静默安装 Node.js，请稍候..." -ForegroundColor Cyan
        
        # 静默安装MSI
        Start-Process msiexec.exe -ArgumentList "/i `"$nodeInstaller`" /qn /norestart" -Wait -NoNewWindow
        
        # 刷新环境变量
        $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
        
        # 清理安装文件
        Remove-Item $nodeInstaller -Force -ErrorAction SilentlyContinue
        
        Write-Host "✅ Node.js 安装完成！" -ForegroundColor Green
    }
    else {
        throw "Node.js 下载失败，请检查网络连接"
    }
}

# 安装Silly Tavern
function Install-SillyTavern {
    Show-Section "🎭 步骤 4: 安装 Silly Tavern 主程序" "Magenta"
    
    $installPath = "$env:USERPROFILE\SillyTavern"
    
    # 检查是否已存在
    if (Test-Path $installPath) {
        Write-Host "⚠️  检测到已存在的 SillyTavern 目录" -ForegroundColor Yellow
        Write-Host "📂 位置: $installPath" -ForegroundColor Yellow
        $response = Read-Host "是否删除并重新安装？(Y/N)"
        if ($response -eq 'Y' -or $response -eq 'y') {
            Write-Host "🗑️  正在删除旧版本..." -ForegroundColor Yellow
            Remove-Item -Path $installPath -Recurse -Force
        }
        else {
            Write-Host "⏭️  跳过克隆步骤，使用现有目录" -ForegroundColor Cyan
            Set-Location $installPath
            return
        }
    }
    
    Write-Host "📥 正在从 Gitee 仓库拉取主程序..." -ForegroundColor Cyan
    Write-Host "🔗 仓库地址: https://gitee.com/dudu-pill/SillyTavern.git" -ForegroundColor Gray
    Write-Host ""
    
    Set-Location $env:USERPROFILE
    
    # 执行git clone
    git clone https://gitee.com/dudu-pill/SillyTavern.git
    
    if ($LASTEXITCODE -eq 0) {
        Write-Host "✅ SillyTavern 主程序克隆成功！" -ForegroundColor Green
        Set-Location $installPath
    }
    else {
        throw "Git 克隆失败"
    }
}

# 安装依赖包
function Install-Dependencies {
    Show-Section "📦 步骤 5: 安装 SillyTavern 依赖模块" "Yellow"
    
    Write-Host "⚙️  配置 npm 使用国内镜像源..." -ForegroundColor Cyan
    npm config set registry https://registry.npmmirror.com
    Write-Host "✅ npm 镜像源已设置为: https://registry.npmmirror.com" -ForegroundColor Green
    Write-Host ""
    
    Write-Host "📦 正在安装 Silly Tavern 内部模块..." -ForegroundColor Cyan
    Write-Host "⏳ 此过程可能需要数分钟，请耐心等待..." -ForegroundColor Yellow
    Write-Host "☕ 您可以趁此机会喝杯咖啡休息一下~" -ForegroundColor Gray
    Write-Host ""
    
    # 显示一个旋转的等待动画
    $job = Start-Job -ScriptBlock {
        Set-Location $using:PWD
        npm install 2>&1
    }
    
    $spinChars = @('⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏')
    $i = 0
    
    while ($job.State -eq 'Running') {
        Write-Host "`r$($spinChars[$i % $spinChars.Length]) 正在安装依赖包..." -NoNewline -ForegroundColor Cyan
        Start-Sleep -Milliseconds 100
        $i++
    }
    
    $result = Receive-Job -Job $job
    Remove-Job -Job $job
    
    Write-Host "`r✅ 依赖包安装完成！                    " -ForegroundColor Green
    Write-Host ""
}

# 创建桌面快捷方式
function Create-DesktopShortcut {
    Show-Section "🔗 步骤 6: 创建桌面启动器" "Green"
    
    $desktopPath = [Environment]::GetFolderPath("Desktop")
    $shortcutPath = "$desktopPath\启动SillyTavern.bat"
    
    $batContent = @"
@echo off
chcp 65001 >nul
title Silly Tavern 启动器
echo.
echo ========================================
echo    🎭 Silly Tavern 正在启动...
echo ========================================
echo.
cd /d "%USERPROFILE%\SillyTavern"
npm start
"@
    
    Set-Content -Path $shortcutPath -Value $batContent -Encoding UTF8
    
    Write-Host "✅ 桌面启动器创建成功！" -ForegroundColor Green
    Write-Host "📂 位置: $shortcutPath" -ForegroundColor Gray
}

# 首次启动
function Start-SillyTavern {
    Show-Section "🚀 步骤 7: 首次启动 Silly Tavern" "Magenta"
    
    Write-Host "🎉 正在为您启动 Silly Tavern..." -ForegroundColor Cyan
    Write-Host "🌐 浏览器将自动打开，请稍候..." -ForegroundColor Yellow
    Write-Host ""
    Write-Host "💡 提示: 如需停止服务，请在命令窗口按 Ctrl+C" -ForegroundColor Gray
    Write-Host ""
    
    Start-Sleep -Seconds 2
    
    # 启动应用
    npm start
}

# 显示成功消息
function Show-SuccessMessage {
    Write-Host ""
    Write-Host "╔═══════════════════════════════════════════════════════════════════╗" -ForegroundColor Green
    Write-Host "║                                                                   ║" -ForegroundColor Green
    Write-Host "║          🎉🎉🎉  恭喜！安装成功完成！ 🎉🎉🎉                    ║" -ForegroundColor Green
    Write-Host "║                                                                   ║" -ForegroundColor Green
    Write-Host "╚═══════════════════════════════════════════════════════════════════╝" -ForegroundColor Green
    Write-Host ""
    Write-Host "  ✅ Silly Tavern 已全部署完毕并已为您自动启动！" -ForegroundColor Cyan
    Write-Host "  🖥️  桌面上已创建 '启动SillyTavern.bat' 快捷方式" -ForegroundColor Cyan
    Write-Host "  🔄 下次双击它即可快速启动" -ForegroundColor Cyan
    Write-Host "  🌐 现在，请查看新弹出的浏览器窗口开始体验吧！" -ForegroundColor Yellow
    Write-Host ""
    Write-Host "  📖 使用提示:" -ForegroundColor Magenta
    Write-Host "     • 默认访问地址: http://localhost:8000" -ForegroundColor Gray
    Write-Host "     • 停止服务: 在命令窗口按 Ctrl+C" -ForegroundColor Gray
    Write-Host "     • 重新启动: 双击桌面上的启动器" -ForegroundColor Gray
    Write-Host ""
    Write-Host "  💖 祝您使用愉快！" -ForegroundColor Magenta
    Write-Host ""
}

#endregion

#region 主程序执行流程

try {
    # 检查管理员权限
    $isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
    
    if (-not $isAdmin) {
        Write-Host "⚠️  警告: 建议以管理员身份运行此脚本以确保顺利安装" -ForegroundColor Yellow
        Write-Host "💡 右键点击 PowerShell 并选择 '以管理员身份运行'" -ForegroundColor Yellow
        Write-Host ""
        $continue = Read-Host "是否继续？(Y/N)"
        if ($continue -ne 'Y' -and $continue -ne 'y') {
            exit
        }
    }
    
    # 步骤 1: 显示欢迎界面
    Show-WelcomeBanner
    
    Show-Section "🔍 步骤 1: 环境检测" "Green"
    Write-Host "🖥️  操作系统: $([System.Environment]::OSVersion.VersionString)" -ForegroundColor Gray
    Write-Host "👤 用户目录: $env:USERPROFILE" -ForegroundColor Gray
    Write-Host "📁 安装位置: $env:USERPROFILE\SillyTavern" -ForegroundColor Gray
    Write-Host ""
    
    # 步骤 2: 安装Git
    Install-Git
    
    # 步骤 3: 安装Node.js
    Install-NodeJS
    
    # 步骤 4: 克隆SillyTavern
    Install-SillyTavern
    
    # 步骤 5: 安装依赖
    Install-Dependencies
    
    # 步骤 6: 创建桌面快捷方式
    Create-DesktopShortcut
    
    # 显示成功消息
    Show-SuccessMessage
    
    # 步骤 7: 首次启动
    Start-SillyTavern
}
catch {
    Write-Host ""
    Write-Host "❌ 错误: 安装过程中出现异常" -ForegroundColor Red
    Write-Host "📝 错误详情: $_" -ForegroundColor Red
    Write-Host ""
    Write-Host "💡 建议:" -ForegroundColor Yellow
    Write-Host "   1. 检查网络连接是否正常" -ForegroundColor Gray
    Write-Host "   2. 确保以管理员身份运行脚本" -ForegroundColor Gray
    Write-Host "   3. 检查磁盘空间是否充足" -ForegroundColor Gray
    Write-Host "   4. 尝试关闭杀毒软件后重试" -ForegroundColor Gray
    Write-Host ""
    Read-Host "按回车键退出"
    exit 1
}

#endregion